/*****************************************************************************
 *   Copyright 2005 Tim A Wang
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 ****************************************************************************/
package com.jb.faces.el;

import com.jb.util.Meter;
import com.jb.web.bean.validator.ValidationError;
import com.jb.web.context.WebContext;

import javax.servlet.jsp.el.ELException;
import javax.servlet.jsp.el.FunctionMapper;
import javax.servlet.jsp.el.VariableResolver;

import org.apache.commons.el.Coercions;
import org.apache.commons.el.ExpressionEvaluatorImpl;
import org.apache.commons.el.Logger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class AttributeEvaluator extends ExpressionEvaluatorImpl {
    protected static Log log = LogFactory.getLog(AttributeEvaluator.class.getName());
    private FunctionMapper functionMapper;
    private VariableResolver resovler;
   
    public AttributeEvaluator(WebContext ctx, Object component) {
        resovler = new JBVariableResolver(ctx, component);
        functionMapper = new JBFunctionMapper(ctx);
    }
 
    
    public static Object convertValue(Object strValue, Class classType) {
        try {
            return Coercions.coerce(strValue, classType, new Logger(System.out));
        } catch (Exception e) {
            return strValue;
        }
    }

    public static Object evaluate(WebContext ctx, Object comp, String expression)
        throws ELException {
        if ((expression == null) || (expression.length() == 0)) {
            return "";
        }

        if (expression.indexOf("${") == -1) {
            return expression;
        }

        Object obj = evaluate(ctx, comp, expression, Object.class);

        return obj;
    }

    public static String validate(Boolean test, String message)
        throws ValidationError {
        if ((test != null) && test.booleanValue()) {
            return "jbSUCCES";
        }

        return message;
    }

    public Object evaluate(String pExpression, Class pExpectedType, VariableResolver pVariableResolver,
        FunctionMapper pFunctionMapper) throws ELException {
        Meter.start();
        pExpression = pExpression.trim();

        if (pVariableResolver == null) {
            pVariableResolver = resovler;
        }

        if (pFunctionMapper == null) {
            pFunctionMapper = functionMapper;
        }

        Object obj =  super.evaluate(pExpression, pExpectedType, pVariableResolver, pFunctionMapper);
        Meter.stop("Evalue "+pExpression);
        return obj;
    }

    public Object evaluate(String pExpression, Class pTargetType)
        throws ELException {
        return evaluate(pExpression, pTargetType, resovler, functionMapper);
    }

    public static Object evaluate(WebContext ctx, Object comp, String expression, Class targetClass)
        throws ELException {
        if ((expression != null) && (expression.indexOf("${") != -1)) {
            try {
                AttributeEvaluator aEvaluator = new AttributeEvaluator(ctx, comp);

                return aEvaluator.evaluate(expression, targetClass);
            } catch (Exception e) {
                ctx.addErrorMessage(expression, e.getMessage());
                return null;
            }
        } else {
            if(targetClass!=null)
                return convertValue(expression, targetClass);
            else
                return expression;
        }
    }
}
